In [74]:
%pylab inline
import numpy as np
from matplotlib import pyplot as plt
The goal of this seminar is to build two simple (anv very similar) face recognition pipelines using scikit-learn package. Overall, we'd like to explore different representations and see which one works better.
In [75]:
import scipy.io
image_h, image_w = 32, 32
data = scipy.io.loadmat('faces_data.mat')
X_train = data['train_faces'].reshape((image_w, image_h, -1)).transpose((2, 1, 0)).reshape((-1, image_h * image_w))
y_train = (data['train_labels'] - 1).ravel()
X_test = data['test_faces'].reshape((image_w, image_h, -1)).transpose((2, 1, 0)).reshape((-1, image_h * image_w))
y_test = (data['test_labels'] - 1).ravel()
n_features = X_train.shape[1]
n_train = len(y_train)
n_test = len(y_test)
n_classes = len(np.unique(y_train))
print('Dataset loaded.')
print(' Image size : {}x{}'.format(image_h, image_w))
print(' Train images : {}'.format(n_train))
print(' Test images : {}'.format(n_test))
print(' Number of classes : {}'.format(n_classes))
Now we are going to plot some samples from the dataset using the provided helper function.
In [76]:
def plot_gallery(images, titles, h, w, n_row=3, n_col=6):
"""Helper function to plot a gallery of portraits"""
plt.figure(figsize=(1.5 * n_col, 1.7 * n_row))
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)
for i in range(n_row * n_col):
plt.subplot(n_row, n_col, i + 1)
plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray, interpolation='nearest')
plt.title(titles[i], size=12)
plt.xticks(())
plt.yticks(())
In [77]:
titles = [str(y) for y in y_train]
plot_gallery(X_train, titles, image_h, image_w)
The simplest way to do face recognition is to treat raw pixels as features and perform Nearest Neighbor Search in the Euclidean space. Let's use KNeighborsClassifier class.
In [78]:
from sklearn.neighbors import KNeighborsClassifier
nc = KNeighborsClassifier(n_neighbors = 3)
nc.fit(X_train, y_train)
test_score = nc.score(X_test, y_test)
print('Test score: {}'.format(test_score))
Not very imperssive, is it?
All the dirty work will be done by the scikit-learn package. First we need to learn a dictionary of codewords. For that we preprocess the training set by making each face normalized (zero mean and unit variance)..
In [79]:
# Populate variable 'X_train_processed' with samples each of which has zero mean and unit variance.
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_processed = scaler.fit_transform(X_train.astype(float))
X_test_processed = scaler.transform(X_test.astype(float))
Now we are going to apply PCA to obtain a dictionary of codewords.
RamdomizedPCA class is what we need.
In [80]:
from sklearn.decomposition import RandomizedPCA
def apply_pca(train, test, nc):
pca = RandomizedPCA(n_components = nc)
pca.fit(train)
train_pca = pca.transform(train)
test_pca = pca.transform(test)
return train_pca, test_pca, pca
X_train_pca, X_test_pca, pca = apply_pca(X_train_processed, X_test_processed, 64)
We plot a bunch of principal components.
In [81]:
# Visualize principal components.
plt.figure(figsize=(20,20))
for i in range(64):
plt.subplot(8, 8, i + 1)
plt.imshow(pca.components_[i].reshape(32, 32), cmap=plt.cm.gray, interpolation='nearest')
plt.xticks(())
plt.yticks(())
Transform training data, train an SVM and apply it to the encoded test data.
In [82]:
from sklearn.svm import SVC
def calc_svc_score(train_x, train_y, test_x, test_y):
svc = SVC(kernel = 'linear')
svc.fit(train_x, train_y)
return svc.score(test_x, test_y)
print('Test score: {}'.format(calc_svc_score(X_train_pca, y_train, X_test_pca, y_test)))
How many components are sufficient to reach the same accuracy level?
In [83]:
n_components = [1, 2, 4, 8, 16, 32, 64]
accuracy = []
for nc in n_components:
X_train_pca, X_test_pca, pca = apply_pca(X_train_processed, X_test_processed, nc)
accuracy.append(calc_svc_score(X_train_pca, y_train, X_test_pca, y_test))
plt.figure(figsize=(10, 6))
plt.plot(n_components, accuracy)
print('Max accuracy: {}'.format(max(accuracy)))